﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using SimpleGame.Font;

namespace SimpleGame.ScreenManagement
{
    /// <summary>
    /// A screen 
    /// </summary>
    public class ScreenManager : DrawableGameComponent
    {
        #region Fields

        // Holds all the game screens that the game has
        private List<GameScreen> screens;
        private List<GameScreen> screensToUpdate = new List<GameScreen>();

        private static SpriteBatch spriteBatch;
        private GraphicsDevice graphicsDevice;

        bool isInitialized;

        #endregion

        #region Properties

        /// <summary>
        /// The SpriteBatch used to draw stuff.
        /// </summary>
        public static SpriteBatch SpriteBatch
        {
            get { return spriteBatch; }
        }

        #endregion

        #region Constructor

        public ScreenManager(Game game)
            : base(game)
        {
            screens = new List<GameScreen>();
            game.IsMouseVisible = true;

        }

        #endregion

        #region XNA Methods

        public override void Initialize()
        {
            base.Initialize();

            isInitialized = true;
        }


        protected override void LoadContent() 
        {
            ContentManager content = Game.Content;
            spriteBatch = new SpriteBatch(Game.GraphicsDevice);
            graphicsDevice = Game.GraphicsDevice;

            // reference the SpriteBatch to the FontManager for easier use of the draw methods there
            FontManager.Instance.SpriteBatchRef = spriteBatch;

            // load the menu item font and add it to the FontManager
            SpriteFont spriteFont = content.Load<SpriteFont>(@"font/menuitem");
            SimpleFont font = new SimpleFont(spriteFont, "menuitem");
            FontManager.Instance.AddFont(font);

            // load the menu title font and add it to the FontManager
            spriteFont = content.Load<SpriteFont>(@"font/menutitle");
            font = new SimpleFont(spriteFont, "menutitle");
            FontManager.Instance.AddFont(font);

            // load content for all screens
            foreach (GameScreen screen in screens)
            {
                screen.LoadContent();
            }
        }

        protected override void UnloadContent()
        {
            foreach (GameScreen screen in screens)
            {
                screen.UnloadContent();
            }
        }

        public override void Update(GameTime gameTime)
        {
            // Make a copy of the master screen list, to avoid confusion if
            // the process of updating one screen adds or removes others.
            screensToUpdate.Clear();

            foreach (GameScreen screen in screens)
            {
                screensToUpdate.Add(screen);
            }

            // Loop as long as there are screens waiting to be updated.
            while (screensToUpdate.Count > 0)
            {
                // Pop the topmost screen off the waiting list.
                GameScreen screen = screensToUpdate[screensToUpdate.Count - 1];

                screensToUpdate.RemoveAt(screensToUpdate.Count - 1);

                // Update the screen.
                screen.Update(gameTime);
            }
        }

        public override void Draw(GameTime gameTime)
        {
            foreach (GameScreen screen in screens)
            {
                screen.Draw(gameTime);
            }
        }

        #endregion

        #region Methods

        public void AddScreen(GameScreen screen)
        {
            screen.ScreenManager = this;

            // If we have a graphics device, tell the screen to load content.
            if (isInitialized)
            {
                screen.LoadContent();
            }

            screens.Add(screen);
        }

        public void RemoveScreen(GameScreen screen)
        {
            // If we have a graphics device, tell the screen to unload content.
            if (isInitialized)
            {
                screen.UnloadContent();
            }
            screens.Remove(screen);
        }

        #endregion
    }
}
